//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <flstatus.h>
#include <flreq.h>
#include <flsocket.h>
#include <fatfilt.h>
#include <flioctl.h>
#include <blockdev.h>
#include <config.h>

static unsigned long  memAddr = RAM_START;
static IOreq ioreqPar;

IOreq* IoreqPar(FLHandle irHandle, unsigned int irFlags, void *irData, long irLength, long irCount)
{
    ioreqPar.irHandle=(irHandle<<4)+0;
    ioreqPar.irFlags=irFlags;
    ioreqPar.irData=irData;
    ioreqPar.irLength=irLength;
    ioreqPar.irCount=irCount;
    return &ioreqPar;
}

int docInit()
{
    bdkInit();
    return 0;
}

int IdentifyDoc(void)
{
    IOreq   ioreq;
    PhysicalInfo    info;

    FLStatus status;
    status = flInit();
    if (noOfSockets == 0)
        return 0;

    ioreq.irHandle = 0;
    ioreq.irData = &info;
    if (flGetPhysicalInfo (&ioreq) != flOK)
        return 0;

    printk("DOC size 0x%lx\n", info.mediaSize);
    printk("DOC unit size 0x%lx\n", info.unitSize);
    printk("DOC type 0x%d\n\n", info.mediaType );

    return 1;
}

int GetBinaryPartitionInfo()
{
    BDKStruct BDKStructRec;
    FLStatus  status;

    memcpy(BDKStructRec.oldSign, "BIPO", 4);
    memcpy(BDKStructRec.newSign, "LOGO", 4);

    status = bdkPartitionInfo(IoreqPar(1, 0, &BDKStructRec, 0, 0));
    if (status == flOK) {
        printk("GetBinaryPartitionInfo-----ok!\n");
        printk("BinaryPartition0 length = %d\n", ioreqPar.irLength / 1024);
        printk("sub Partition0 length = %d\n", BDKStructRec.length / 1024);
        printk("sub Partition0 startblock = %d\n", BDKStructRec.startingBlock);
        printk("Number of binary partitions = %d\n", BDKStructRec.flags);
    }
    else
        printk("GetBinaryPartitionInfo-----failed!\n");
}

int CreateBinarySubpartition(int subPartitionNo, int length, unsigned char sign[4])
{
    BDKStruct BDKStructRec;
    FLStatus  status;

    BDKStructRec.startingBlock = 0;
    BDKStructRec.length = length;
    BDKStructRec.signOffset=8;

    memcpy (BDKStructRec.oldSign, "BDKP", 4);
    memcpy (BDKStructRec.newSign, sign, 4);
    /* memcpy (BDKStructRec.newSign, "LOGO", 4); */

    /* memcpy(BDKStructRec.oldSign, "BIPO", 4); */
    /* memcpy(BDKStructRec.newSign, "LOGO", 4); */

    status = bdkCreate(IoreqPar(subPartitionNo,0, &BDKStructRec, 0, 0));

    BDKStructRec.signOffset=8;
    BDKStructRec.startingBlock=0;
    memcpy (BDKStructRec.oldSign, sign, 4);
    status = bdkPartitionInfo (IoreqPar(1,0,&BDKStructRec,0,0) );
    printk ( "number of sub-partition = 0x%x\r\n", BDKStructRec.flags );
    printk ( "size of sub-partition = %ld = %dK\r\n", BDKStructRec.startingBlock, BDKStructRec.startingBlock/1024 );

    if (status == flOK)
        return 1;

    printk("CreateBinarySubpartition----failed---status = %d\n", status);

    return 0;

/*  bdkStruct.length=(clParams.subPart[b].dwSize%physicalInfo.unitSize)?clParams.subPart[b].dwSize/physicalInfo.unitSize+1:clParams.subPart[b].dwSize/physicalInfo.unitSize; */

/*  memcpy(bdkStruct.oldSign,clParams.binaryFp[b>>3].sign,BINARY_SIGNATURE_NAME); */
/* ExMemCpy (bdkStruct.newSign,clParams.subPart[b].sign,BINARY_SIGNATURE_NAME); */
/* bdkStruct.signOffset=8;  */
/* bdkStruct.startingBlock=0; */
/* CheckStat (bdkCreate (SetIoreq ((b>>3)<<4,0,&bdkStruct,0,0)),FL_BINARY_CREATE); */
/*  } */
/*  return EX_OK; */
}

int FormatDoc()
{
    FormatParams2 fp = STD_FORMAT_PARAMS2;
    BDTLPartitionFormatParams bdtlP[] = { STD_BDTL_PARAMS, STD_BDTL_PARAMS, STD_BDTL_PARAMS, STD_BDTL_PARAMS };
    BinaryPartitionFormatParams bdkP[] = { STD_BINARY_PARAMS, STD_BINARY_PARAMS,STD_BINARY_PARAMS };
    IOreq ioreq;
    FLStatus status;

    ioreqPar.irHandle = 0;  //initial value is 0
    /* BDTL info */
    fp.noOfBDTLPartitions = BDTL_NUMBER;
    bdtlP[0].length = BDTL0_LENGTH;
    bdtlP[0].flags = TL_NORMAL_FORMAT;
    bdtlP[1].length = BDTL1_LENGTH;
    bdtlP[1].flags = TL_NORMAL_FORMAT;

    fp.BDTLPartitionInfo = bdtlP;
      /* ioreq.irFlags = TL_FORMAT_FAT; */
    ioreq.irFlags = TL_NORMAL_FORMAT;

    /* BDK info */
      /* fp.noOfBinaryPartitions = BDK_NUMBER; */
      /* bdkP[0].length = BDK0_LENGTH; */
    /* bdkP[0].flags  = TL_SPL_FORMAT; */
      /* bdkP[1].length = BDK1_LENGTH; */

    fp.noOfBinaryPartitions = 2;
    bdkP[0].length = 1*1024*1024;
    bdkP[0].flags  = TL_SPL_FORMAT;
    memcpy(bdkP[0].sign, "BOOT", 4);
    bdkP[1].length = 2*1024*1024;
    memcpy(bdkP[1].sign, "BDKP", 4);           // new name for BDK1

    fp.binaryPartitionInfo = bdkP;

    status = flFormatPhysicalDrive( IoreqPar(0,0,&fp,0,0) );
    if (status != flOK) {
        return 0;
    }
    else {
        CreateBinarySubpartition(1, 4, "LOGO");
        CreateBinarySubpartition(1, 4, "TATA");
        CreateBinarySubpartition(1, 4, "TATB");
        return 1;
    }
}

int WriteIPL()
{
    unsigned char *ptr = (unsigned char*)memAddr;
    FLStatus status;

    status = flWriteIPL(IoreqPar(0,FL_IPL_MODE_NORMAL,ptr,2*1024,0) );
    if (status != flOK) {
        return 0;
    }
    else
        return 1;
}

int WriteSPL()
{
    BDKStruct BDKStructRec;
    FLStatus status;
    unsigned char * ptr=(unsigned char*)memAddr;

    memcpy(BDKStructRec.oldSign, "BOOT", 4);
    memcpy(BDKStructRec.newSign, "BOOT", 4);
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = BDK0_LENGTH;
    BDKStructRec.flags = BDK_COMPLETE_IMAGE_UPDATE;

    status = bdkWriteInit(IoreqPar(0,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = ptr;
    BDKStructRec.length = BDK0_LENGTH;

    status = bdkWriteBlock(IoreqPar(0, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        return 0;
    }
    else {
        return 1;
    }
}

int WriteLogo()
{
    BDKStruct BDKStructRec;
    FLStatus status;
    unsigned char * ptr=(unsigned char*)memAddr;

    memcpy (BDKStructRec.oldSign, "LOGO", 4);
        /* memcpy (BDKStructRec.newSign, "BIPO", 4); */
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = /* LOGO_SUBPARTITION */256*1024;

    status = bdkWriteInit(IoreqPar (0x01,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = ptr;
    BDKStructRec.length = /* LOGO_SUBPARTITION */256*1024;

    status = bdkWriteBlock (IoreqPar (0x01, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        return 0;
    }
    else {
        return 1;
    }
}

int ReadLogo()
{
    BDKStruct BDKStructRec;
    FLStatus status;

    unsigned char buf[1*1024*1024];

    tffscpy( BDKStructRec.oldSign, "LOGO", 4 );
    /* tffscpy( BDKStructRec.newSign, "BIPO", 4 ); */
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = 256*1024;
    status = bdkReadInit ( IoreqPar (0x1,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        printk ("ReadLogo-----bdkReadInit----------failed\n");
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = buf;
    BDKStructRec.length = 256*1024;

    status = bdkReadBlock ( IoreqPar (0x1, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        printk ("ReadLogo-----bdkReadBlock----------failed\n");
        return 0;
    }

    int i = 0, j = 0;
    for (i = 0; i < 400; i++) {
        for (j = 0; j < 16; j++) {
            printk ("%x ", *(buf + i * 16 + j));
        }
        if ((i + 1) % 16 == 0)
            printk ("\n                                                              \n");
        printk ("\n");
    }

    return 1;
}

int WriteTAT()
{
    BDKStruct BDKStructRec;
    FLStatus status;
    unsigned char * ptr=(unsigned char*)memAddr;

    memcpy (BDKStructRec.oldSign, "LOGO", 4);
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = 256*1024;

    status = bdkWriteInit(IoreqPar (0x01,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = ptr;
    BDKStructRec.length = 256*1024;

    status = bdkWriteBlock (IoreqPar (0x01, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        return 0;
    }
    else {
        return 1;
    }
}

int ReadTAT()
{
    BDKStruct BDKStructRec;
    FLStatus status;

    unsigned char buf[1*1024*1024];

    tffscpy( BDKStructRec.oldSign, "LOGO", 4 );
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = 256*1024;
    status = bdkReadInit ( IoreqPar (0x1,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        printk ("ReadTAT-----bdkReadInit----------failed\n");
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = buf;
    BDKStructRec.length = 256*1024;

    status = bdkReadBlock ( IoreqPar (0x1, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        printk ("ReadTAT-----bdkReadBlock----------failed\n");
        return 0;
    }

    int i = 0, j = 0;
    for (i = 0; i < 400; i++) {
        for (j = 0; j < 16; j++) {
            printk ("%2x ", *(buf + i * 16 + j));
        }
        if ((i + 1) % 16 == 0)
            printk ("\n                                                              \n");
        printk ("\n");
    }

    return 1;
}

int WriteTatTable(unsigned char *buff)
{
    BDKStruct BDKStructRec;
    FLStatus status;
    unsigned char * ptr=(unsigned char*)buff;

    memcpy (BDKStructRec.oldSign, "LOGO", 4);
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = 256*1024;

    status = bdkWriteInit(IoreqPar (0x01,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = ptr;
    BDKStructRec.length = 256*1024;

    status = bdkWriteBlock (IoreqPar (0x01, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        printk("WriteTatTable Error\n");
        return 0;
    }
    else {
        return 1;
    }
}

int ReadTatTable(unsigned char *buff)
{
    BDKStruct BDKStructRec;
    FLStatus status;

    tffscpy( BDKStructRec.oldSign, "LOGO", 4 );
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = 256*1024;
    status = bdkReadInit ( IoreqPar (0x1,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        printk ("ReadTAT-----bdkReadInit----------failed\n");
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = buff;
    BDKStructRec.length = 256*1024;

    status = bdkReadBlock ( IoreqPar (0x1, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        printk ("ReadTAT-----bdkReadBlock----------failed\n");
        return 0;
    }

    int i = 0, j = 0;
    for (i = 0; i < 400; i++) {
        for (j = 0; j < 16; j++) {
            printk ("%2x ", *(buff + i * 16 + j));
        }
        if ((i + 1) % 16 == 0)
            printk ("\n                                                              \n");
        printk ("\n");
    }

    return 1;
}

int WriteKernel()
{
    BDKStruct BDKStructRec;
    FLStatus status;
    unsigned char * ptr=(unsigned char*)memAddr;

    memcpy(BDKStructRec.oldSign, "BDKP", 4);
        /* memcpy(BDKStructRec.oldSign, "BIPO", 4); */
    /* memcpy(BDKStructRec.newSign, "BIPO", 4); */
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = /* BDK1_LENGTH */1*2024*1024;
    BDKStructRec.flags = BDK_COMPLETE_IMAGE_UPDATE;

    status = bdkWriteInit(IoreqPar(0x01,0,&BDKStructRec,0,0) );
    if (status != flOK) {
        return 0;
    }

    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = ptr;
    BDKStructRec.length = /* BDK1_LENGTH */1*1024*1024;

    status = bdkWriteBlock(IoreqPar(0x01, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        return 0;
    }
    else {
        return 1;
    }
}

int LoadKernel(to)
{
    BDKStruct BDKStructRec;
    FLStatus  status;
    unsigned char* ptr = (unsigned char*)to;

    tffscpy(BDKStructRec.oldSign, "BDKP", 4);
    /* tffscpy(BDKStructRec.oldSign, "BIPO", 4); */
    /* tffscpy(BDKStructRec.newSign, "BIPO", 4); */
    BDKStructRec.startingBlock = 0;
    BDKStructRec.signOffset = 8;
    BDKStructRec.length = /* BDK1_LENGTH */1*1024*1024;
    status = bdkReadInit (IoreqPar (1, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        printk("doc_read_os----bdkReadInit----------failed\n");
        return 1;
    }
    BDKStructRec.startingBlock = 0;
    BDKStructRec.bdkBuffer = ptr;
    BDKStructRec.length = /* BDK1_LENGTH */1*1024*1024;

    status = bdkReadBlock (IoreqPar (1, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        printk("doc_read_os----bdkReadBlock----------failed\n");
        return 1;
    }

    return 0;
}

int doc_BDTL_mount(unsigned int partition)
{
    IOreq ioreq;
    FLStatus stat;

    ioreq.irHandle=(partition << 4) + 0;
    stat=flAbsMountVolume(&ioreq);
    if (stat == flOK)
        return 1;
    else {
        printk("doc_BDTL_mount->flAbsMountVolume error %d\n",stat);
        return 0;
    }
}

int doc_BDTL_dismount(unsigned int partition)
{
    IOreq ioreq;
    FLStatus stat;

    ioreq.irHandle=(partition << 4) + 0;
    stat=flDismountVolume(&ioreq);
    if (stat != flOK) {
        printk("doc_BDTL_dismount->flDismountVolume error %d\n",stat);
        return 0;
    }
    else
        return 1;
}

int doc_info(void)
{

    GetBinaryPartitionInfo();

    IOreq    ioreq;
    FLStatus status;
    doc_BDTL_mount(0);
    ioreq.irHandle = 0x0;
    status = flSectorsInVolume(&ioreq);
    if (status == flOK)
        printk("BDTL0-----sectors = 0x%x\n", ioreq.irLength);

    doc_BDTL_dismount(0);

    doc_BDTL_mount(1);
    ioreq.irHandle = 0x10;
    status = flSectorsInVolume(&ioreq);
    if (status == flOK)
        printk("BDTL1-----sectors = 0x%x\n", ioreq.irLength);
    doc_BDTL_dismount(1);

    return 0;
}

int Get_BDTL_Partition_Size(unsigned int ParNo)
{
    IOreq    ioreq;
    FLStatus status;

    ioreq.irHandle = (ParNo << 4) & 0xf0;
    status = flSectorsInVolume(&ioreq);
    if (status == flOK)
        return ioreq.irLength;
    else {
        printk("Get_BDTL_Partiton_Size----error---%d\n", status);
        return status;
    }
}

int ShowLast512Byte()
{
    unsigned char *to = (unsigned char*)0xa3c2f800;

    int i = 0, j = 0;
    for (i = 0; i < 300; i++) {
        for (j = 0; j < 16; j++) {
            printk ("%x ", *(to + i * 16 + j));
        }
        if ((i + 1) % 16 == 0)
            printk ("\n                                                              \n");
        printk ("\n");
    }
    return 1;
}

int bdkInited = 0;

int doc_oneblock_write(unsigned int partition, unsigned char *buf, unsigned int block)
{
    BDKStruct BDKStructRec;
    FLStatus status;
    unsigned char * ptr = (unsigned char*)buf;

    if (!bdkInited) {
        if (partition == 0)
            BDKStructRec.length = BDK0_LENGTH;
        if (partition == 1)
            BDKStructRec.length = BDK1_LENGTH;

        tffscpy( BDKStructRec.oldSign, "BIPO", 4 );
        BDKStructRec.startingBlock = 0;
        BDKStructRec.signOffset = 8;
        status = bdkWriteInit( IoreqPar(partition,0,&BDKStructRec,0,0) );
        if (status != flOK) {
            printk("bdkWriteInit----------failed\n");
            return 0;
        }
        bdkInited = 1;
    }
    BDKStructRec.startingBlock = block;
    BDKStructRec.bdkBuffer = ptr;
    BDKStructRec.length = DOC_BLOCK_SIZE;

    status = bdkWriteBlock( IoreqPar(partition, 0, &BDKStructRec, 0, 0) );
    if (status != flOK) {
        printk("bdkWriteBlock----------failed\n");
        return 0;
    }

    return 1;
}

int doc_oneblock_BDTL_write(unsigned int partition, unsigned char *buf, unsigned int block)
{
    IOreq ioreq;
    FLStatus stat;

    ioreq.irHandle=(partition << 4) + 0;
    ioreq.irData=buf;
    ioreq.irSectorNo=block*DOC_PAGES_IN_BLOCK;
    ioreq.irSectorCount=DOC_PAGES_IN_BLOCK;
//Bill
    printk("DOC: block=%d\n", block);
    stat=flAbsWrite(&ioreq);
    if (stat == flOK)
        return 1;
    else {
        printk("doc_oneblock_BDTL_write->flAbsWrite error %d",stat);
        return 0;
    }
}

int WriteRootFs()
{
    printk("WriteRootFs---111111\n");
    IOreq ioreq;
    FLStatus stat;

    unsigned char * ptr=(unsigned char*)memAddr;

    doc_BDTL_mount(0x0);
    printk ("WriteRootFs---222222\n");

    ioreq.irHandle=(0x0 << 4) + 0;
    ioreq.irData=ptr;
    ioreq.irSectorNo=0;
    printk ("WriteRootFs---3333333\n");
    ioreq.irSectorCount=Get_BDTL_Partition_Size(0);
    printk ("WriteRootFs------Partition Size = 0x%x\n", ioreq.irSectorCount);
    stat=flAbsWrite(&ioreq);
    doc_BDTL_dismount(0x0);
    if (stat == flOK)
        return 1;
    else {
        printk("WriteRootFs->flAbsWrite error %d",stat);
        return 0;
    }
}

int WriteMMI()
{
    IOreq ioreq;
    FLStatus stat;

    unsigned char * ptr=(unsigned char*)memAddr;

    printk("WriteMMI---1111111111111\n");
    doc_BDTL_mount(0x1);
    printk ("WriteMMI---222222222222\n");

    ioreq.irHandle=(0x1 << 4) & 0xf0;
    ioreq.irData=ptr;
    ioreq.irSectorNo=0;
    ioreq.irSectorCount=Get_BDTL_Partition_Size(1);
    printk("WriteMMI------Partition Size = 0x%x\n", ioreq.irSectorCount);

    stat=flAbsWrite(&ioreq);
    printk ("WriteMMI---3333333333333333\n");
    doc_BDTL_dismount(0x1);
    printk ("WriteMMI---4444444444444444\n");
    if (stat == flOK)
        return 1;
    else {
        printk("WriteMMI->flAbsWrite error %d",stat);
        return 0;
    }
}

int doc_read_rootfs()
{

    IOreq    ioreq;
    FLStatus stat;

    unsigned char buf[DOC_BLOCK_SIZE * 2];
    memset (buf, 0, DOC_BLOCK_SIZE * 2);

    ioreq.irHandle = 0;
    ioreq.irData = buf;
    ioreq.irSectorNo = 0;
    ioreq.irSectorCount = 4;

    printk ("partition size == %d\r\n",sizeof(PartitionTable));

    doc_BDTL_mount(0);
    stat = flAbsRead(&ioreq);
    doc_BDTL_dismount(0);

    if (stat == flOK) {
        int i = 0, j = 0;
        for (i = 0; i < 400; i++) {
            for (j = 0; j < 16; j++) {
                printk ("%x ", *(buf + i * 16 + j));
            }
            if ((i + 1) % 16 == 0)
                printk ("\n                                                              \n");
            printk ("\n");
        }
        return 1;
    }
    else {
        printk ("doc_read_rootfs error %d",stat);
        return 0;
    }
}
